﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;

namespace mstdump_Analyzer
{
    class PortInfoIB : PortInfoInterface
    {
        ArrayList portsArrayList = new ArrayList();
        ArrayList spinePortsArrayList = new ArrayList();
        private bool KEEP_RUNNING; 
        private string OUTPUT_DIR_PATH;
        private bool timeouts = false;
        //
        //----------------------------------------------------
        //
        public PortInfoIB(ref bool KEEP_RUNNING, ref string OUTPUT_DIR_PATH)
        {
            this.KEEP_RUNNING = KEEP_RUNNING;   
            this.OUTPUT_DIR_PATH = OUTPUT_DIR_PATH;
        }
        //
        //----------------------------------------------------
        //
        public DataTable getLeafsPortInfo()
        {
            // create a DataTable
            DataTable table = new DataTable();
            // add columns
            table.Columns.Add("Slot#", typeof(int));
            table.Columns.Add("Port#", typeof(int));
            table.Columns.Add("Slot Type", typeof(string));
            table.Columns.Add("Logical port state", typeof(string));
            table.Columns.Add("Physical port state", typeof(string));
            table.Columns.Add("Current line rate", typeof(string));
            table.Columns.Add("Supported speeds", typeof(string));
            table.Columns.Add("Speed", typeof(string));
            table.Columns.Add("Supported widths", typeof(string));
            table.Columns.Add("Width", typeof(string));
            table.Columns.Add("Max supported MTUs", typeof(string));
            table.Columns.Add("MTU", typeof(string));
            table.Columns.Add("Cable identifier", typeof(string));
            table.Columns.Add("Cable/module type", typeof(string));
            table.Columns.Add("Cable infiniband speeds", typeof(string));
            table.Columns.Add("Cable vendor", typeof(string));
            table.Columns.Add("Cable cable length", typeof(string));
            table.Columns.Add("Cable revision", typeof(string));
            table.Columns.Add("Cable part number", typeof(string));
            table.Columns.Add("Cable serial number", typeof(string));

            //rx
            table.Columns.Add("RX bytes", typeof(long));
            table.Columns.Add("RX packets", typeof(long));
            table.Columns.Add("RX errors", typeof(long));
            table.Columns.Add("Symbol errors", typeof(long));
            table.Columns.Add("VL15 dropped packets", typeof(long));
            
            //tx
            table.Columns.Add("TX bytes", typeof(long));
            table.Columns.Add("TX packets", typeof(long));
            table.Columns.Add("TX wait", typeof(long));
            table.Columns.Add("TX discarded packets", typeof(long));
            

            // add DataRows.
            for (int i = 0; i < portsArrayList.Count; i++)
            {
                PortInfoIBFields pi = (PortInfoIBFields)portsArrayList[i];
                table.Rows.Add(pi.slotNum,
                    pi.portNum,
                    pi.slotType,
                    pi.logicalPortState,
                    pi.physicalPortState,
                    pi.currentLineRate,
                    pi.supportedSpeeds,
                    pi.speed,
                    pi.supportedWidths,
                    pi.width,
                    pi.maxSupportedMTUs,
                    pi.MTU,
                    pi.identifier,
                    pi.cableModuleType,
                    pi.infinibandSpeeds,
                    pi.vendor,
                    pi.cableLength,
                    pi.revision,
                    pi.partNumber,
                    pi.serialNumber,
                    pi.RXBytes,
                    pi.RXPackets,
                    pi.RXErrors,
                    pi.symbolErrors,
                    pi.VL15DroppedPackets,
                    pi.TXBytes,
                    pi.TXPackets,
                    pi.TXWait,
                    pi.TXDiscardedPackets);
            }
            return table;
        }
        //
        //----------------------------------------------------
        //
        public DataTable getSpinesPortInfo()
        {
            // create a DataTable
            DataTable table = new DataTable();
            // add columns
            table.Columns.Add("Slot#", typeof(int));
            table.Columns.Add("Port#", typeof(int));
            table.Columns.Add("Slot Type", typeof(string));
            table.Columns.Add("Connected to slot", typeof(string));
            table.Columns.Add("Connected to port", typeof(int));
            table.Columns.Add("Connected device active", typeof(int));
            table.Columns.Add("Error state", typeof(int));
            table.Columns.Add("Logical port state", typeof(string));
            table.Columns.Add("Physical port state", typeof(string));
            table.Columns.Add("Current line rate", typeof(string));
            table.Columns.Add("Supported speeds", typeof(string));
            table.Columns.Add("Speed", typeof(string));
            table.Columns.Add("Supported widths", typeof(string));
            table.Columns.Add("Width", typeof(string));
            table.Columns.Add("Max supported MTUs", typeof(string));
            table.Columns.Add("MTU", typeof(string));
            table.Columns.Add("VL capabilities", typeof(string));
            table.Columns.Add("Operational VLs", typeof(string));
            table.Columns.Add("Description", typeof(string));

            // add DataRows.
            for (int i = 0; i < spinePortsArrayList.Count; i++)
            {
                SpinePortInfoIBFields pi = (SpinePortInfoIBFields)spinePortsArrayList[i];
                table.Rows.Add(pi.slotNum,
                    pi.portNum,
                    pi.slotType,
                    pi.connectedToSlot,
                    pi.connectedToPort,
                    pi.connectedDeviceActive,
                    pi.errorState,
                    pi.logicalPortState,
                    pi.physicalPortState,
                    pi.currentLineRate,
                    pi.supportedSpeeds,
                    pi.speed,
                    pi.supportedWidths,
                    pi.width,
                    pi.maxSupportedMTUs,
                    pi.MTU,
                    pi.VLCapabilities,
                    pi.operationalVLs,
                    pi.description);
            }
            return table;
        }
        //
        //----------------------------------------------------
        //
        public void scanPortInfo(object param)
        {
            string srcFilePath = (string)param;
            if (srcFilePath == null)
                return;
            StreamReader sr = new StreamReader(srcFilePath);
            try
            {
                while (KEEP_RUNNING && sr.Peek() >= 0)
                {
                    if (sr.ReadLine().Contains("port info"))
                    {
                        break;
                    }
                }
                PortInfoIBFields tmpPort = null;
                SpinePortInfoIBFields spineTmpPort = null;
                int index = 0;
                Boolean scanningPorts = true;
                string slotType = "";
                while (KEEP_RUNNING && sr.Peek() >= 0)
                {
                    // read line
                    string line = sr.ReadLine();
                    if (line.Contains("timed out after"))
                    {
                        timeouts = true;
                    }
                    try
                    {
                        if (scanningPorts)
                        {
                            // port info
                            if (line.Contains("Slot"))
                            {
                                string tmp = Regex.Split(line, " ")[1];
                                slotType = "1U";
                                // line/spine ?
                                if (tmp.Contains("L"))
                                {
                                    tmp = Regex.Replace(tmp, "L", "");
                                    slotType = "Leaf";
                                }
                                if (tmp.Contains("S"))
                                {
                                    tmp = Regex.Replace(tmp, "S", "");
                                    slotType = "Spine";
                                }
                                int slotNum = Int32.Parse(tmp);
                                int portNum = Int32.Parse(Regex.Split(line, " ")[3]);

                                if (slotType.Equals("Spine"))
                                {
                                    if (spinePortsArrayList.Count < (36 * (slotNum - 1)) + portNum)
                                    {
                                        spineTmpPort = new SpinePortInfoIBFields();
                                        // set slot and port numbers
                                        spineTmpPort.slotNum = slotNum;
                                        spineTmpPort.portNum = portNum;
                                        spineTmpPort.slotType = slotType;
                                    }
                                    else
                                    {
                                        scanningPorts = false;
                                    }
                                }
                                else
                                {
                                    if (portsArrayList.Count < (18 * (slotNum - 1)) + portNum)
                                    {
                                        tmpPort = new PortInfoIBFields();
                                        // set slot and port numbers
                                        tmpPort.slotNum = slotNum;
                                        tmpPort.portNum = portNum;
                                        tmpPort.slotType = slotType;
                                    }
                                    else
                                    {
                                        scanningPorts = false;
                                    }
                                }

                            } //if (line.Contains("Slot"))
                            else
                            { // FabricIT
                                if (line.Contains("Module"))
                                {
                                    int slotNum = 0, portNum = 0;
                                    string tmp = Regex.Split(line, " ")[1];
                                    slotType = "1U";
                                    // line/spine ?
                                    if (tmp.Contains("L"))
                                    {
                                        slotType = "Leaf";
                                        tmp = Regex.Replace(tmp, "L", "");
                                        slotNum = Int32.Parse(tmp);
                                        portNum = Int32.Parse(Regex.Split(line, " ")[3]);
                                    }
                                    else if (tmp.Contains("IS"))
                                    {
                                        slotType = "1U";
                                        slotNum = 1;
                                        portNum = Int32.Parse(Regex.Split(line, " ")[3]);
                                    }
                                    else if (tmp.Contains("S"))
                                    {
                                        slotType = "Spine";
                                        tmp = Regex.Replace(tmp, "S", "");
                                        slotNum = Int32.Parse(tmp);
                                        portNum = Int32.Parse(Regex.Split(line, " ")[4]);
                                    }

                                    if (slotType.Equals("Spine"))
                                    {
                                        if (spinePortsArrayList.Count < (36 * (slotNum - 1)) + portNum)
                                        {
                                            spineTmpPort = new SpinePortInfoIBFields();
                                            // set slot and port numbers
                                            spineTmpPort.slotNum = slotNum;
                                            spineTmpPort.portNum = portNum;
                                            spineTmpPort.slotType = slotType;
                                        }
                                        else
                                        {
                                            scanningPorts = false;
                                        }
                                    }
                                    else
                                    {
                                        if (portsArrayList.Count < (18 * (slotNum - 1)) + portNum)
                                        {
                                            tmpPort = new PortInfoIBFields();
                                            // set slot and port numbers
                                            tmpPort.slotNum = slotNum;
                                            tmpPort.portNum = portNum;
                                            tmpPort.slotType = slotType;
                                        }
                                        else
                                        {
                                            scanningPorts = false;
                                        }
                                    }

                                }//if (line.Contains("Module"))
                            }
                            if (slotType.Equals("Spine"))
                            {
                                if (line.Contains("Connected to slot"))
                                {
                                    spineTmpPort.connectedToSlot = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Connected to port"))
                                {
                                    spineTmpPort.connectedToPort = Int32.Parse(Regex.Split(line, ":")[1]);
                                }
                                if (line.Contains("Connected device active"))
                                {
                                    spineTmpPort.connectedDeviceActive = Int32.Parse(Regex.Split(line, ":")[1]);
                                }
                                // Leaf is active
                                if (line.Contains("Leaf is active"))
                                {
                                    spineTmpPort.connectedDeviceActive = Int32.Parse(Regex.Split(line, ":")[1]);
                                }
                                if (line.Contains("Error state "))
                                {
                                    spineTmpPort.errorState = Int32.Parse(Regex.Split(line, ":")[1]);
                                }
                                if (line.Contains("Logical port state"))
                                {
                                    spineTmpPort.logicalPortState = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Physical port state"))
                                {
                                    spineTmpPort.physicalPortState = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Current line rate"))
                                {
                                    spineTmpPort.currentLineRate = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Supported speeds"))
                                {
                                    spineTmpPort.supportedSpeeds = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Speed"))
                                {
                                    spineTmpPort.speed = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Supported widths"))
                                {
                                    spineTmpPort.supportedWidths = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Width"))
                                {
                                    spineTmpPort.width = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Max supported MTUs"))
                                {
                                    spineTmpPort.maxSupportedMTUs = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("MTU"))
                                {
                                    spineTmpPort.MTU = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("VL capabilities"))
                                {
                                    spineTmpPort.VLCapabilities = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Operational VLs"))
                                {
                                    spineTmpPort.operationalVLs = Regex.Split(line, ":")[1];
                                    spinePortsArrayList.Add(spineTmpPort);
                                }
                                if (line.Contains("Description"))
                                {
                                    //spineTmpPort.description = Regex.Split(line, ":")[1];
                                    //spinePortsArrayList.Add(spineTmpPort);
                                    ((SpinePortInfoIBFields)spinePortsArrayList[spinePortsArrayList.Count - 1]).description = Regex.Split(line, ":")[1];
                                }
                            }// if (slotType.Equals("Spine"))
                            else // leaf
                            {
                                if (line.Contains("Logical port state"))
                                {
                                    tmpPort.logicalPortState = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Physical port state"))
                                {
                                    tmpPort.physicalPortState = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Current line rate"))
                                {
                                    tmpPort.currentLineRate = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Supported speeds"))
                                {
                                    tmpPort.supportedSpeeds = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Speed"))
                                {
                                    tmpPort.speed = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Supported widths"))
                                {
                                    tmpPort.supportedWidths = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Width"))
                                {
                                    tmpPort.width = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Max supported MTUs"))
                                {
                                    tmpPort.maxSupportedMTUs = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("MTU"))
                                {
                                    tmpPort.MTU = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("VL capabilities"))
                                {
                                    tmpPort.VLCapabilities = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Operational VLs"))
                                {
                                    tmpPort.operationalVLs = Regex.Split(line, ":")[1];
                                }
                                if (line.Contains("Description"))
                                {
                                    tmpPort.description = Regex.Split(line, ":")[1];
                                }
                                //
                                if (line.Contains("RX bytes"))
                                {
                                    tmpPort.RXBytes = long.Parse(Regex.Split(line, ":")[1]);
                                }
                                if (line.Contains("RX packets"))
                                {
                                    tmpPort.RXPackets = long.Parse(Regex.Split(line, ":")[1]);
                                }
                                if (line.Contains("RX errors"))
                                {
                                    tmpPort.RXErrors = long.Parse(Regex.Split(line, ":")[1]);
                                }
                                if (line.Contains("Symbol errors"))
                                {
                                    tmpPort.symbolErrors = long.Parse(Regex.Split(line, ":")[1]);
                                }
                                if (line.Contains("VL15 dropped packets"))
                                {
                                    tmpPort.VL15DroppedPackets = long.Parse(Regex.Split(line, ":")[1]);
                                }
                                //
                                if (line.Contains("TX bytes"))
                                {
                                    tmpPort.TXBytes = long.Parse(Regex.Split(line, ":")[1]);
                                }
                                if (line.Contains("TX packets"))
                                {
                                    tmpPort.TXPackets = long.Parse(Regex.Split(line, ":")[1]);
                                }
                                if (line.Contains("TX wait"))
                                {
                                    tmpPort.TXWait = long.Parse(Regex.Split(line, ":")[1]);
                                    portsArrayList.Add(tmpPort);
                                }
                                if (line.Contains("TX discarded packets"))
                                {
                                    //tmpPort.TXDiscardedPackets = long.Parse(Regex.Split(line, ":")[1]);
                                    //portsArrayList.Add(tmpPort);
                                    ((PortInfoIBFields)portsArrayList[portsArrayList.Count - 1]).TXDiscardedPackets = long.Parse(Regex.Split(line, ":")[1]);
                                }
                            } // if (!tmpPort.slotType.Equals("Spine"))
                        } //if (scanningPorts)
                        else
                        {
                            // connected cable info
                            if (line.Contains("identifier"))
                            {
                                ((PortInfoIBFields)portsArrayList[index]).identifier = Regex.Split(line, ":")[1];
                            }
                            if (line.Contains("cable/ module type"))
                            {
                                ((PortInfoIBFields)portsArrayList[index]).cableModuleType = Regex.Split(line, ":")[1];
                            }
                            if (line.Contains("infiniband speeds"))
                            {
                                ((PortInfoIBFields)portsArrayList[index]).infinibandSpeeds = Regex.Split(line, ":")[1];
                            }
                            if (line.Contains("vendor"))
                            {
                                ((PortInfoIBFields)portsArrayList[index]).vendor = Regex.Split(line, ":")[1];
                            }
                            if (line.Contains("cable length"))
                            {
                                ((PortInfoIBFields)portsArrayList[index]).cableLength = Regex.Split(line, ":")[1];
                            }
                            if (line.Contains("part number"))
                            {
                                ((PortInfoIBFields)portsArrayList[index]).partNumber = Regex.Split(line, ":")[1];
                            }
                            if (line.Contains("revision"))
                            {
                                ((PortInfoIBFields)portsArrayList[index]).revision = Regex.Split(line, ":")[1];
                            }
                            if (line.Contains("serial number"))
                            {
                                ((PortInfoIBFields)portsArrayList[index]).serialNumber = Regex.Split(line, ":")[1];
                                // increase the index 
                                index++;
                            }
                        }

                    }//try
                    catch
                    {
                    }
                    if (line.Contains("licenses info"))
                    {
                        sr.Dispose();
                        return;
                    }
                }
            }//try
            catch 
            {
            }
            sr.Dispose();
        }
        //
        //----------------------------------------------------
        //
        public bool getTimeoutState()
        {
            return timeouts;
        }
    }  
}
